那一排,都是穿黑衣戴口罩的,去幫我找出搗亂的。抱歉,我只能給你 -1 因為連我們偶爾都會穿黑衣戴口罩。
終於,我們要進入ECMAScript 5 的陣列方法了!
ECMAScript 5 定義了許多很重要的陣列方法,包括了過濾、檢測、遍歷、搜索和鏡射的方法,讓我們能更輕易的操控陣列與陣列元素。
但是今天是週末,我們先來介紹相對比較沒那麼複雜的indexOf()
。
indexOf()
方法像是一個會通風報信的吹哨人,請它去幫忙找出陣列裡面的某個指定元素,它就會 明查暗訪 幫我們把這個元素找出來,並告訴我們這個元素在哪個位置(索引值),它只會給我們「第一個」找到的位置 表示有交差,如果沒有找到,indexOf()
就會回傳給我們 -1 表示在陣列裡找不到這個元素。
Array.prototype.indexOf() - JavaScript | MDN
原型: Array.prototype.indexOf()
功能: 搜尋陣列中指定的值。
改變: 不會改變原陣列。
語法: arr.indexOf(searchElement[, fromIndex])
回傳值: 在陣列中找到的第一個元素索引值;沒找到則為 -1。
參數: 要找的元素、從哪裡開始找。
為了不混淆,我們以字串元素來示範
const arr = ["a", "b", "c", "D", "C", "b", "a"];
// 沒給參數,不知道我們要找的元素是什麼,回傳 -1 很合理。
arr.indexOf(); // -1
// 找到的 "c" 在索引值 2 的位置
arr.indexOf("c"); // 2
// 從索引值 2 的位置開始找,所以找到第二個 "b"
arr.indexOf("b", 2); // 5
// 從索引值 3 的位置開始找,會區分大小寫,找不到 "c" 回傳 -1
arr.indexOf("c", 3); // -1
// 第二參數預設就是 0 ,這裡有寫沒寫都ㄧ樣
arr.indexOf("c", 0); // 2
// 第二參數 -5 表示從後面數過來 -5 的位置開始找,所以找得到 "c"
arr.indexOf("c", -5); // 2
// 但是從 -5 開始找就找不到"c" 所以回傳 -1
arr.indexOf("c", -4); // -1
indexOf()
可帶兩個參數,第一個參數searchElement
是指定要找尋的元素,第二個參數fromIndex
索引值,不是必須,表示要從哪一個位置開始搜尋。如果這個索引值大於或等於陣列的長度,會直接回傳 -1,因為要開始搜尋的元素都已經超過陣列長度,自然搜尋就起不了作用。
如果給的fromIndex
索引值是一個負數,就會從陣列的最後一個往回算,等同最後一個的索引值是 -1,以此類推。
雖然表示往回算,但indexOf()
的搜尋順序依然會從陣列的左往右一一搜尋。如果負數索引值在回頭計算之後仍然小於 0,則會從左往右全部搜尋。
這個參數的預設值為 0(即搜尋整個陣列)。還有,indexOf()
並不像其他大部分的ECMAScript 5 陣列方法一樣,參數可以帶函式,帶函式參數對indexOf()
是無效的。
雖然indexOf()
只會回傳給我們第一個找到的元素位置,但是我們可以使用迴圈,將陣列裡面所有符合搜尋條件元素的索引值,放在一個陣列裡:
function findAll(arr,element){
const results = [];
let len = arr.length;
let fromIndex = 0;
while(fromIndex < len){
fromIndex = arr.indexOf(element, fromIndex);
if(fromIndex === -1) break; // 沒找到完成搜尋
results.push(fromIndex); // 將找到的索引值放入陣列
fromIndex = fromIndex + 1;
}
return results;
}
let result = findAll(arr,"b")
result; // [1, 5]
如果可以將找到的索引位置的值,集中放入陣列裡是不是更方便?indexOf()
雖然無法直接做到,但是有其他方法可以做到這些,例如 ECMAScript 5 的filter
或 ECMAScript 6 的find()
都可以輕易辦到。
和某些部分陣列的方法ㄧ樣,indexOf()
是無法直接查找參考型別的元素,像是陣列、物件,需要將這些元素指定給一個變數,這個變數在陣列裡,就可使用indexOf()
到。
const arr2 = ["a", {a:42} ]
arr2.indexOf("a"); // 0 找得到
arr2.indexOf({a:42}); // -1 找不到
// 將元素指定給變數
const arr = [1,2];
const arr3 = [42, arr ]
arr3.indexOf(arr); // 1
const obj = {a:42}
const arr4 = ["a", obj, 12]
arr4.indexOf(obj); // 1
其實,還有另一個indexOf()
的孿生陣列方法lastIndexOf()
功能和indexOf()
差不多 簡直ㄧ樣,我們明天可以來聊聊,順便穿插一些輕鬆題外話~敬請期待囉~
才剛要介紹 ECMAScript 5 的陣列方法,鐵人賽就快要結束了,那 ECMAScript 6 呢? 不長進的留到明年寫嗎? 參加鐵人賽所獲得的,也不只是介紹這些方法而已。因鐵人賽讓本人開始了解查找資料的樂趣 大嬸瘋了 所以,應該會繼續不定期寫下去喔~
如有需要改進的地方,拜託懇求請告知,我會盡量快速度修改,感謝您~
最後提的:「參考型別的元素無法找」,我覺得有些奇怪
不是沒辦法找,是照原文中那樣子不可能找到
對 indexOf 這個方法來說,無論你找什麼都是沒差的
都只是在比較 array 裡面是否有元素 === 你要找的東西
原文的例子要找的 {a:42} 跟 arr 裡面的 {a:42} 位置不同,自然不會相等
換成底下這樣就找得到了:
const obj = {a:42}
const arr = [0, 1, 2, obj]
console.log(arr.indexOf(obj)) //3
原來可以這樣用,我都沒想到!太感謝胡大了!
晚點來修改。
您好~
請問關於文中的『過濾、檢測、遍歷、搜索和鏡射』,想確認相對應的正確英文,
filter 過濾
map 遍歷
sort 搜索
檢測 ?
鏡射 ?
謝謝~
const arr = ["a", "b", "c", "D", "C", "b", "a"];
// 從索引值 2 的位置開始找,所以找到第二個 "b"
arr.indexOf("b", 2); // 5
在這個部分有點不太能理解,從第二個位置開始找,
以陣列的第二個位置來說不是小寫的 "c" 嗎?
那 arr.indexOf("b", 2);
意思是:
那結論應該是 3 才對吧?
因為從陣列第二個位置("c")要找("b")表示向右找 3 次才找到 "b" 的,但結果是 5 這部分有點疑惑@@
function findAll(arr,element){
const results = [];
let len = arr.length;
let fromIndex = 0;
while(fromIndex < len){
fromIndex = arr.indexOf(element, fromIndex);
if(fromIndex === -1) break; // 沒找到完成搜尋
results.push(fromIndex); // 將找到的索引值放入陣列
fromIndex = fromIndex + 1;
}
return results;
}
let result = findAll(arr,"b")
result; // [1, 5]
這一段結果應該是 arr is not defined